package com.kexio.scheduler.config;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import com.kexio.scheduler.service.SchedulerService;
import com.kexio.scheduler.service.impl.SchedulerServiceImpl;

/**
 * 定时任务自动配置
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
@Configuration
@ConditionalOnProperty(prefix = "kexio.scheduler", name = "enabled", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(SchedulerProperties.class)
@ComponentScan(basePackages = "com.kexio.scheduler")
@EnableScheduling
@EnableAsync
public class SchedulerAutoConfiguration {
    
    private static final Logger logger = LoggerFactory.getLogger(SchedulerAutoConfiguration.class);
    
    private final SchedulerProperties properties;
    
    public SchedulerAutoConfiguration(SchedulerProperties properties) {
        this.properties = properties;
        logger.info("Kexio Scheduler 模块正在初始化...");
    }
    
    /**
     * 配置调度器任务执行线程池
     */
    @Bean("schedulerTaskExecutor")
    @ConditionalOnMissingBean(name = "schedulerTaskExecutor")
    public Executor schedulerTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        SchedulerProperties.ThreadPool threadPool = properties.getThreadPool();
        
        executor.setCorePoolSize(threadPool.getCorePoolSize());
        executor.setMaxPoolSize(threadPool.getMaximumPoolSize());
        executor.setKeepAliveSeconds((int) threadPool.getKeepAliveTime());
        executor.setQueueCapacity(threadPool.getQueueCapacity());
        executor.setThreadNamePrefix(threadPool.getThreadNamePrefix());
        
        // 拒绝策略：由调用者执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        
        // 等待任务完成后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setAwaitTerminationSeconds(60);
        
        executor.initialize();
        
        logger.info("定时任务线程池配置完成 - 核心线程数: {}, 最大线程数: {}, 队列容量: {}",
                   threadPool.getCorePoolSize(), threadPool.getMaximumPoolSize(), threadPool.getQueueCapacity());
        
        return executor;
    }
    
    /**
     * 配置调度器服务
     */
    @Bean
    @ConditionalOnMissingBean
    public SchedulerService schedulerService() {
        logger.info("创建 SchedulerService Bean");
        return new SchedulerServiceImpl();
    }
    
    /**
     * 监控配置Bean
     */
    @Bean
    @ConditionalOnProperty(prefix = "kexio.scheduler.monitor", name = "enabled", havingValue = "true", matchIfMissing = true)
    public SchedulerMonitorConfiguration schedulerMonitorConfiguration() {
        logger.info("启用定时任务监控");
        return new SchedulerMonitorConfiguration(properties);
    }
    
    /**
     * 集群配置Bean
     */
    @Bean
    @ConditionalOnProperty(prefix = "kexio.scheduler.cluster", name = "enabled", havingValue = "true")
    public SchedulerClusterConfiguration schedulerClusterConfiguration() {
        logger.info("启用定时任务集群模式");
        return new SchedulerClusterConfiguration(properties);
    }
    
    /**
     * 监控配置内部类
     */
    public static class SchedulerMonitorConfiguration {
        private final SchedulerProperties properties;
        
        public SchedulerMonitorConfiguration(SchedulerProperties properties) {
            this.properties = properties;
        }
        
        public SchedulerProperties getProperties() {
            return properties;
        }
    }
    
    /**
     * 集群配置内部类
     */
    public static class SchedulerClusterConfiguration {
        private final SchedulerProperties properties;
        
        public SchedulerClusterConfiguration(SchedulerProperties properties) {
            this.properties = properties;
        }
        
        public SchedulerProperties getProperties() {
            return properties;
        }
    }
}
